#ifndef PRESENTATION_H_
#define PRESENTATION_H_

#include <OgreCamera.h>
#include <OgreEntity.h>
#include <OgreLogManager.h>
#include <OgreRoot.h>
#include <OgreViewport.h>
#include <OgreSceneManager.h>
#include <OgreRenderWindow.h>
#include <OgreConfigFile.h>
#include <OgreCamera.h>

#include <OgreWindowEventUtilities.h>

#include "../GameLogic/Level/Level.h"

namespace Graphics {

/**
 * Klasa odpowiadajaca za obsluge i generacje wszystkich elementow powiazanych z wyswietlaniem rozgrywki,
 * jednak nie majacych nic wspolnego z sama logika gry. Obejmuje to obsluge animacji, efektow czasteczkowych,
 * kamery, etc. Dodatkowo klasa Presentation inicjalizuje i komunikuje sie z biblioteka graficzna.
 */
class Presentation : public Ogre::WindowEventListener {
    Ogre::Root* root_;
    Ogre::Camera* main_cam_;
    Ogre::SceneManager* scene_manager_;
    Ogre::RenderWindow* render_window_;

    GameLogic::Level::Level* level_;

    /* Szerokosc okna. */
    int width_;
    /* Wysokosc okna. */
    int height_;

    Presentation();
    ~Presentation();

public:

    static float toOgreCoords( float val ) {
    	return 10.0f * val;
    }

    /**
     * Robi sfere o zadanych parametrach.
     */
    static void createSphere(const std::string& strName, const float r, const int nRings, const int nSegments, const std::string& useMaterial = "BaseWhite");

    static Presentation& getInstance() {
    	static Presentation instance;
    	return instance;
    }

    void initializeGame( GameLogic::Level::Level* level ) {
    	level_ = level;
    }

    void windowResized( Ogre::RenderWindow* rw );

    void windowClosed( Ogre::RenderWindow* rw );

    /*
     * Renderuje kolejna klatke. Aktualizuje takze stan animacji, oraz uaktualnia pozycje kamery.
     */
    void render( long dt );

    /*
     * Inicjalizuje Ogre.
     */
    bool init();

    /*
     * Zamyka Ogre.
     */
    void close();

#ifdef HAHA_NIE_MA_TAKIEGO_DEFINEA_ASDGASVCERSGFD_DWUKROPEKDUZEPE

    Ogre::Entity* createEntity( const Ogre::String& entity_name, const Ogre::String& mesh_name ) {
    	return scene_manager_->createEntity( entity_name, mesh_name );
    }

	Ogre::SceneNode* createSceneNode( const Ogre::String& name, const Ogre::Vector3& position, const Ogre::Quaternion& rotation ) {

		/*

		Ogre::SceneManager* scene_manager = Graphics::Presentation::getInstance().getSceneManager();

		createSphere("mesh" + boost::lexical_cast< std::string >( id_.toNumeric() ), Graphics::Camera::Camera::toOgreCoord( getRadius() ), 12, 12);

		entity_ = scene_manager->createEntity("Head" + boost::lexical_cast< std::string >( id_.toNumeric() ), "mesh" + boost::lexical_cast< std::string >( id_.toNumeric() ));
		scene_node_ = scene_manager->createSceneNode();
		scene_manager->getRootSceneNode()->addChild( scene_node_ );
		scene_node_->attachObject( entity_ );

		 */

		Ogre::SceneNode* sn = scene_manager_->createSceneNode( name );
		scene_manager_->getRootSceneNode()->addChild( sn );
		sn->setPosition( position );
		sn->rotate( rotation );
		return sn;
	}

	Ogre::SceneNode* createSceneNode( const Ogre::String& name, const Ogre::Vector3& position ) {
		return createSceneNode( name, position, Ogre::Quaternion::ZERO );
	}

	Ogre::SceneNode* createSceneNode( const Ogre::String& name, const Vec2f& position ) {
		return createSceneNode( name, Ogre::Vector3( position.x, position.y, 0.0f ), Ogre::Quaternion::ZERO );
	}

	Ogre::SceneNode* createSceneNode( const Ogre::String& name ) {
		return createSceneNode( name, Ogre::Vector3::ZERO, Ogre::Quaternion::ZERO );
	}

#endif

	/*
	 * Tworzy SceneNode, ktorej rodzicem jest root node.
	 */
	Ogre::SceneNode* createSceneNode( Ogre::Entity* entity );

	/*
	 * Tworzy SceneNode, ktorej rodzicem jest parent.
	 */
	Ogre::SceneNode* createSceneNode( Ogre::Entity* entity, Ogre::SceneNode* parent );

	void destroySceneNode( Ogre::SceneNode* node ) {
		scene_manager_->destroySceneNode( node );
	}

	Ogre::RenderWindow* getWindow() {
		return render_window_;
	}

	Ogre::SceneManager* getSceneManager() {
		return scene_manager_;
	}

	Ogre::Camera* getCamera() {
		return main_cam_;
	}

};

} //namespace Graphics

#endif /* PRESENTATION_H_ */
